import 'dart:convert';
import 'dart:io';
import 'package:dio/adapter.dart';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter_rider/main/widgets/dialog/loading_dialog.dart';
import 'package:flutter_rider/main/widgets/ext/u_text.dart';
import 'package:flutter_rider/module/login/models/user_model.dart';
import 'package:flutter_rider/module/login/provider/user_provider.dart';
import 'package:flutter_rider/utils/screen_fit.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../app.dart';
import '../config.dart';
import '../event/logout_event.dart';
import '../kit/mqtt_kit.dart';
import '../main.dart';

import '../main/widgets/ui_constant.dart';

import '../utils/log.dart';
import '../utils/tip.dart';
import 'package:provider/provider.dart';

class ServerResponse {
  int code = 0;
  dynamic data;
  String msg = "";

  parse(dynamic json) {
    // Log.i(json);
    try {
      code = json["code"];
      data = json["data"];
      msg = json["msg"] ?? "";
    } catch (e) {
      Log.e(e);
    }
  }
}

class ApiCode {
  static const OK = 1;
  static const SESSION_INVALID = -100000;
}

class EnvHost {
  // static const TEST = "http://127.0.0.1:8087"; // 本地Tate

  // static const TEST = "http://192.168.1.10:8087"; // Tate
  // static const TEST = "http://192.168.1.86:8087";// 嘉隆
  static const TEST = "https://sctestdriverapi.sxpei.cn";
  static const PRE = "https://scpredriverapi.sxpei.cn";
  static const RELEASE = "https://scdriverapi.sxpei.cn";
}

class Api {
  static final _dio = Dio();
  static var HOST = EnvHost.RELEASE;
  static var PROXY = "";
  static var API = HOST + "/v1/app";
  static dynamic _loginInfo = {};
  static const _loginKey = "login_info";
  static late SharedPreferences _sp;

  static init(WidgetRef ref) async {
    //Log.i("init");
    _sp = await SharedPreferences.getInstance();
    if (_sp.containsKey(_loginKey)) {
      _loginInfo = jsonDecode(_sp.getString(_loginKey) ?? "");
      ref
          .read(userModelProvider.notifier)
          .setUserModel(UserModel.fromMap(_loginInfo));
      // context.read<UserModelProvider>().setUserModel(UserModel.fromMap(_loginInfo));
      //Log.i("has login: ${_loginInfo.length}");
    }
    if (App.isDebugMode) {
      var host = _sp.getString("debug_host");
      if (host != null && host.isNotEmpty) {
        HOST = host;
      }
      var proxy = _sp.getString("debug_proxy");
      if (proxy != null && proxy.isNotEmpty) {
        PROXY = proxy;
      }
    }
    //设置连接超时时间为15秒
    _dio.options.connectTimeout = 15000; //15s
    // _dio.options.receiveTimeout = 5000;
    (_dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
        (client) {
      client.badCertificateCallback =
          (X509Certificate cert, String host, int port) {
        return Platform.isAndroid;
      };
      client.findProxy = (uri) {
        if (PROXY.isEmpty) {
          return "DIRECT";
        } else {
          return "PROXY $PROXY";
        }
      };
    };

    App.initRef(ref);
  }

  static void setHost(String host) {
    HOST = host;
    API = HOST + "/v1/app";
    _sp.setString("debug_host", host);
  }

  static void setProxy(String proxy) {
    PROXY = proxy;
    _sp.setString("debug_proxy", proxy);
  }

  static logout() async {
    _loginInfo = {};
    await _sp.remove(_loginKey);
    MqttKit.instance.destroy();
  }

  static bool isLogin() {
    return _loginInfo.length > 0;
  }

  static Map getUserInfo() {
    return _loginInfo;
  }

  ///获取上次登录的账号
  static String getAccount() {
    return _sp.getString(Config.kAccountKey) ?? "";
  }

  ///用户转模型
  static UserModel getUserModel() {
    return UserModel.fromMap(_loginInfo);
  }

  static saveLoginInfo(dynamic data) async {
    _loginInfo = data;
    await _sp.setString(_loginKey, jsonEncode(_loginInfo));
    //记录手机账号
    _sp.setString(Config.kAccountKey, Api.getUserModel().mobile);
    initButton(data);
  }

  static SharedPreferences getSp() {
    return _sp;
  }

  static request(String path, String method, dynamic data,
      Function(dynamic data, ServerResponse response) callback,
      {CancelToken? cancelToken}) async {
    ServerResponse serverResponse = ServerResponse();
    var headers = <String, dynamic>{};
    try {
      headers["token"] = _loginInfo["token"];
      Log.i('请求头 -----> $headers');
      var url = path;
      if (!path.startsWith("http")) {
        url = API + path;
      }
      Log.i(url);
      Log.i(data);
      var options = Options(method: method, headers: headers);
      var response = await _dio.request(url,
          options: options, data: data, cancelToken: cancelToken);
      if (cancelToken != null) {
        if (cancelToken.isCancelled) {
          return Future.value(null);
        }
      }
      Log.i('response', response);
      if (response.data != null) {
        var code = response.data["code"];
        if (code == ApiCode.OK && response.data["data"] == null) {
          response.data["data"] = {};
        }
        serverResponse.parse(response.data);
        if (code == ApiCode.SESSION_INVALID) {
          _handlerLogout();
        }
      }
    } on DioError catch (e) {
      Log.e(e.toString());
      if (e.response != null && e.response?.data != null) {
        serverResponse.parse(e.response?.data);
      }
    } catch (e) {
      Log.i(e);
    }
    if (serverResponse.code == ApiCode.OK) {
      callback(serverResponse.data, serverResponse);
    } else {
      callback(null, serverResponse);
    }
  }

  static initButton(data) async {
    _sp = await SharedPreferences.getInstance();
    _sp.setBool("_showZh", false);
    _sp.setBool("_showXh", false);
    _sp.setBool("_showDispatch", false);
    _sp.setBool("_showUndistributed", false);
    data["menu"].forEach((element) {
      if (element["name"] == "工作台") {
        element["menu"].forEach((data) {
          if (data["name"] == "装货") {
            _sp.setBool("_showZh", true);
          }
          if (data["name"] == "卸货") {
            _sp.setBool("_showXh", true);
          }
          if (data["name"] == "调车") {
            _sp.setBool("_showDispatch", true);
          }
        });
      }
    });
  }

  static _handlerLogout() async {
    var sp = await SharedPreferences.getInstance();
    await sp.remove(_loginKey);
    eventBus.fire(LogoutEvent());
  }

  static void get(
      String path, Function(dynamic data, ServerResponse response) callback,
      {CancelToken? cancelToken}) {
    request(path, "GET", null, callback, cancelToken: cancelToken);
  }

  static Future<void> getSync(
      String path, Function(dynamic data, ServerResponse response) callback,
      {CancelToken? cancelToken}) async {
    await request(path, "GET", null, callback, cancelToken: cancelToken);
  }

  static void post(String path, dynamic data,
      Function(dynamic data, ServerResponse response) callback) {
    request(path, "POST", data, callback);
  }

  static void requestx(BuildContext context, String path, String method,
      {dynamic data,
      String content = "",
      Function(dynamic data)? success,
      Function(ServerResponse response)? fail,
      String? successTip,
      String? failTip,
      progress = true}) {
    cb() {
      LoadingDialog? dialog;
      if (progress) {
        dialog = LoadingDialog(context);
        dialog.show();
      }
      request(path, method, data, (data, response) {
        dialog?.hide();
        if (data != null) {
          if (successTip != null && successTip.isNotEmpty) {
            Tip.show(successTip);
          }
          if (success != null) {
            success(data);
          }
        } else {
          if (failTip != null && failTip.isNotEmpty) {
            Tip.show(failTip, serverResponse: response);
            Log.i(
                "请求失败URL：$path ------> $failTip ------> 信息：${response.msg} 失败状态码：${response.code}");
          }
          if (fail != null) {
            fail(response);
          }
        }
      });
    }

    ;
    if (content.isNotEmpty) {
      showDialog(
          context: context,
          builder: (context) {
            return AlertDialog(
              title: UText.get("提示", UIColor.color_t1, 18.rpx,
                  fw: FontWeight.w600),
              content: UText.get(content, UIColor.color_t3, 17.rpx),
              actions: [
                TextButton(
                    onPressed: () {
                      Navigator.pop(context, "cancel");
                    },
                    child: UText.get("取消", UIColor.color_t3, 15.rpx)),
                TextButton(
                    onPressed: () {
                      Navigator.pop(context, "yes");
                      cb();
                    },
                    child: UText.get("确定", UIColor.color_primary, 15.rpx)),
              ],
            );
          });
    } else {
      cb();
    }
  }

  static void getx(BuildContext context, String path,
      {String content = "",
      Function(dynamic data)? success,
      Function(ServerResponse response)? fail,
      String? successTip,
      String? failTip,
      bool progress = true}) {
    requestx(context, path, "GET",
        content: content,
        success: success,
        fail: fail,
        successTip: successTip,
        failTip: failTip,
        progress: progress);
  }

  static void submitx(BuildContext context, String path,
      {dynamic data,
      String content = "",
      Function(dynamic data)? success,
      Function(ServerResponse response)? fail,
      String? successTip,
      String? failTip,
      bool progress = true}) {
    requestx(context, path, "POST",
        data: data,
        content: content,
        success: success,
        fail: fail,
        successTip: successTip,
        failTip: failTip,
        progress: progress);
  }

  static void deletex(BuildContext context, String path,
      {String content = "",
      Function(dynamic data)? success,
      Function(ServerResponse response)? fail,
      String? successTip,
      String? failTip,
      bool progress = true}) {
    requestx(context, path, "DELETE",
        content: content,
        success: success,
        fail: fail,
        successTip: successTip,
        failTip: failTip,
        progress: progress);
  }
}
